<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no"
    />
    <meta
      name="description"
      content="Draw a polygon or extruded polygon on the globe surface."
    />
    <meta name="cesium-sandcastle-labels" content="Development" />
    <title>Cesium Demo</title>
    <script type="text/javascript" src="../Sandcastle-header.js"></script>
    <script
      type="text/javascript"
      src="../../../Build/CesiumUnminified/Cesium.js"
      nomodule
    ></script>
    <script type="module" src="../load-cesium-es6.js"></script>
  </head>
  <body
    class="sandcastle-loading"
    data-sandcastle-bucket="bucket-requirejs.html"
  >
    <style>
      @import url(../templates/bucket.css);
    </style>
    <div id="cesiumContainer" class="fullSize"></div>
    <div id="loadingOverlay"><h1>Loading...</h1></div>
    <div id="toolbar"></div>
    <script id="cesium_sandcastle_script">
      function startup(Cesium) {
        "use strict";
        //Sandcastle_Begin
        var viewer = new Cesium.Viewer("cesiumContainer", {
          terrainProvider: Cesium.createWorldTerrain(),
        });
        var scene = viewer.scene;
        viewer.extend(Cesium.viewerCesiumInspectorMixin);

        function offsetPositions(positions, degreeOffset) {
          positions = scene.globe.ellipsoid.cartesianArrayToCartographicArray(
            positions
          );
          var delta = Cesium.Math.toRadians(degreeOffset);
          for (var i = 0; i < positions.length; ++i) {
            var position = positions[i];
            position.latitude += delta;
            position.longitude += delta;
          }
          return scene.globe.ellipsoid.cartographicArrayToCartesianArray(
            positions
          );
        }

        function createOverlappingPolygons(withAlpha) {
          var positions = [
            new Cesium.Cartesian3(
              -2358138.847340281,
              -3744072.459541374,
              4581158.5714175375
            ),
            new Cesium.Cartesian3(
              -2357231.4925370603,
              -3745103.7886602185,
              4580702.9757762635
            ),
            new Cesium.Cartesian3(
              -2355912.902205431,
              -3744249.029778454,
              4582402.154378103
            ),
            new Cesium.Cartesian3(
              -2357208.0209552636,
              -3743553.4420488174,
              4581961.863286629
            ),
          ];
          var polygonHierarchy = { positions: positions };

          var color = Cesium.Color.RED;
          if (withAlpha) {
            color = color.withAlpha(0.5);
          }

          scene.groundPrimitives.add(
            new Cesium.GroundPrimitive({
              geometryInstances: new Cesium.GeometryInstance({
                geometry: new Cesium.PolygonGeometry({
                  polygonHierarchy: polygonHierarchy,
                }),
                attributes: {
                  color: Cesium.ColorGeometryInstanceAttribute.fromColor(color),
                },
                id: "polygon 1",
              }),
              classificationType: Cesium.ClassificationType.TERRAIN,
            })
          );

          // Same polygon slightly offset and overlapping.
          var positionsOffset = offsetPositions(positions, 0.01);
          polygonHierarchy = { positions: positionsOffset };

          color = Cesium.Color.GREEN;
          if (withAlpha) {
            color = color.withAlpha(0.5);
          }

          scene.groundPrimitives.add(
            new Cesium.GroundPrimitive({
              geometryInstances: new Cesium.GeometryInstance({
                geometry: new Cesium.PolygonGeometry({
                  polygonHierarchy: polygonHierarchy,
                }),
                attributes: {
                  color: Cesium.ColorGeometryInstanceAttribute.fromColor(color),
                },
                id: "polygon 2",
              }),
              classificationType: Cesium.ClassificationType.TERRAIN,
            })
          );

          // Same polygon slightly offset and overlapping.
          positionsOffset = offsetPositions(positions, -0.01);
          polygonHierarchy = { positions: positionsOffset };

          color = Cesium.Color.BLUE;
          if (withAlpha) {
            color = color.withAlpha(0.5);
          }

          scene.groundPrimitives.add(
            new Cesium.GroundPrimitive({
              geometryInstances: new Cesium.GeometryInstance({
                geometry: new Cesium.PolygonGeometry({
                  polygonHierarchy: polygonHierarchy,
                }),
                attributes: {
                  color: Cesium.ColorGeometryInstanceAttribute.fromColor(color),
                },
                id: "polygon 3",
              }),
              classificationType: Cesium.ClassificationType.TERRAIN,
            })
          );
        }

        function viewOverlappingPolygons() {
          viewer.camera.lookAt(
            new Cesium.Cartesian3(
              -2354331.3069306486,
              -3742016.2427205616,
              4581875.591571755
            ),
            new Cesium.HeadingPitchRange(
              Cesium.Math.toRadians(20.0),
              Cesium.Math.toRadians(-35.0),
              10000.0
            )
          );
          viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY);
        }

        var handler;

        Sandcastle.addDefaultToolbarButton("Picking Example", function () {
          createOverlappingPolygons(true);
          viewOverlappingPolygons();

          var currentObject;
          var lastColor;

          handler = new Cesium.ScreenSpaceEventHandler(scene.canvas);
          handler.setInputAction(function (movement) {
            var pickedObject = scene.pick(movement.endPosition);
            if (
              Cesium.defined(pickedObject) &&
              pickedObject !== currentObject
            ) {
              if (Cesium.defined(currentObject)) {
                currentObject.primitive.getGeometryInstanceAttributes(
                  currentObject.id
                ).color = lastColor;
              }

              currentObject = pickedObject;

              var attributes = currentObject.primitive.getGeometryInstanceAttributes(
                currentObject.id
              );
              lastColor = attributes.color;
              attributes.color = [255, 255, 0, 128];
            } else if (
              !Cesium.defined(pickedObject) &&
              Cesium.defined(currentObject)
            ) {
              currentObject.primitive.getGeometryInstanceAttributes(
                currentObject.id
              ).color = lastColor;
              currentObject = undefined;
            }
          }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
        });

        Sandcastle.addToolbarButton("Z-Order", function () {
          createOverlappingPolygons(false);
          viewOverlappingPolygons();

          handler = new Cesium.ScreenSpaceEventHandler(scene.canvas);
          handler.setInputAction(function (movement) {
            var pickedObject = scene.pick(movement.endPosition);
            if (Cesium.defined(pickedObject)) {
              scene.groundPrimitives.raiseToTop(pickedObject.primitive);
            }
          }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
        });

        function createBatchedInstances(color, show) {
          var instances = [];

          var width = 0.02561343838881669;
          var height = 0.019831817968480436;

          var lat = 46.18147866629652;
          var lon = -122.20406057655991;

          var delta = 0.03;
          var latDeltas = [0.0, 0.0, delta, 0.0];
          var lonDeltas = [0.0, delta, 0.0, -delta];

          var length = latDeltas.length;
          for (var i = 0; i < length; ++i) {
            lon = lon + lonDeltas[i];
            lat = lat + latDeltas[i];

            var west = lon;
            var east = lon + width;
            var south = lat;
            var north = lat + height;

            instances.push(
              new Cesium.GeometryInstance({
                geometry: new Cesium.RectangleGeometry({
                  rectangle: Cesium.Rectangle.fromDegrees(
                    west,
                    south,
                    east,
                    north
                  ),
                }),
                attributes: {
                  color: color,
                  show: show,
                },
                id: "rectangle" + i,
              })
            );
          }

          return instances;
        }

        Sandcastle.addToolbarButton("Batching", function () {
          var color = new Cesium.ColorGeometryInstanceAttribute(
            0.0,
            1.0,
            1.0,
            0.5
          );
          var show = new Cesium.ShowGeometryInstanceAttribute(true);
          var instances = createBatchedInstances(color, show);
          scene.groundPrimitives.add(
            new Cesium.GroundPrimitive({
              geometryInstances: instances,
              classificationType: Cesium.ClassificationType.TERRAIN,
            })
          );

          viewOverlappingPolygons();
        });

        Sandcastle.addToolbarButton("Batch Picking", function () {
          var color = new Cesium.ColorGeometryInstanceAttribute(
            0.0,
            1.0,
            1.0,
            0.5
          );
          var show = new Cesium.ShowGeometryInstanceAttribute(true);
          var instances = createBatchedInstances(color, show);

          var primitive = scene.groundPrimitives.add(
            new Cesium.GroundPrimitive({
              geometryInstances: instances,
              classificationType: Cesium.ClassificationType.TERRAIN,
            })
          );

          color = new Cesium.ColorGeometryInstanceAttribute(1.0, 0.0, 1.0, 0.5);
          show = new Cesium.ShowGeometryInstanceAttribute(false);
          instances = createBatchedInstances(color, show);

          // Edit id to differentiate between picked primitive and normally displayed primitive.
          var pickIdPrefix = "pick";
          for (var i = 0; i < instances.length; ++i) {
            instances[i].id = pickIdPrefix + instances[i].id;
          }

          var pickPrimitive = scene.groundPrimitives.add(
            new Cesium.GroundPrimitive({
              geometryInstances: instances,
              classificationType: Cesium.ClassificationType.TERRAIN,
            })
          );

          viewOverlappingPolygons();

          var currentObject;

          handler = new Cesium.ScreenSpaceEventHandler(scene.canvas);
          handler.setInputAction(function (movement) {
            var pickedObject = scene.pick(movement.endPosition);
            if (
              Cesium.defined(pickedObject) &&
              pickedObject !== currentObject &&
              pickedObject.id.indexOf(pickIdPrefix) === -1
            ) {
              if (Cesium.defined(currentObject)) {
                primitive.getGeometryInstanceAttributes(
                  currentObject.id
                ).show = [1];
                pickPrimitive.getGeometryInstanceAttributes(
                  pickIdPrefix + currentObject.id
                ).show = [0];
              }

              currentObject = pickedObject;

              primitive.getGeometryInstanceAttributes(currentObject.id).show = [
                0,
              ];
              pickPrimitive.getGeometryInstanceAttributes(
                pickIdPrefix + currentObject.id
              ).show = [1];
            } else if (
              !Cesium.defined(pickedObject) &&
              Cesium.defined(currentObject)
            ) {
              primitive.getGeometryInstanceAttributes(currentObject.id).show = [
                1,
              ];
              pickPrimitive.getGeometryInstanceAttributes(
                pickIdPrefix + currentObject.id
              ).show = [0];
              currentObject = undefined;
            }
          }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
        });

        Sandcastle.addToolbarButton("Create large polygons", function () {
          // Circle geometry
          scene.groundPrimitives.add(
            new Cesium.GroundPrimitive({
              geometryInstances: new Cesium.GeometryInstance({
                geometry: new Cesium.CircleGeometry({
                  center: Cesium.Cartesian3.fromDegrees(-95.0, 45.0),
                  radius: 250000.0,
                }),
                attributes: {
                  color: Cesium.ColorGeometryInstanceAttribute.fromColor(
                    new Cesium.Color(1.0, 0.0, 0.0, 0.5)
                  ),
                },
                id: "circle",
              }),
              classificationType: Cesium.ClassificationType.TERRAIN,
            })
          );

          // Ellipse Geometry
          scene.groundPrimitives.add(
            new Cesium.GroundPrimitive({
              geometryInstances: new Cesium.GeometryInstance({
                geometry: new Cesium.EllipseGeometry({
                  center: Cesium.Cartesian3.fromDegrees(-105.0, 40.0),
                  semiMinorAxis: 300000.0,
                  semiMajorAxis: 400000.0,
                }),
                attributes: {
                  color: Cesium.ColorGeometryInstanceAttribute.fromColor(
                    new Cesium.Color(0.0, 1.0, 1.0, 0.5)
                  ),
                },
                id: "ellipse",
              }),
              classificationType: Cesium.ClassificationType.TERRAIN,
            })
          );

          // Corridor Geometry
          scene.groundPrimitives.add(
            new Cesium.GroundPrimitive({
              geometryInstances: new Cesium.GeometryInstance({
                geometry: new Cesium.CorridorGeometry({
                  positions: Cesium.Cartesian3.fromDegreesArray([
                    -112.0,
                    40.0,
                    -117.0,
                    40.0,
                    -117.0,
                    35.0,
                  ]),
                  width: 200000.0,
                }),
                attributes: {
                  color: Cesium.ColorGeometryInstanceAttribute.fromColor(
                    new Cesium.Color(0.0, 0.0, 1.0, 0.5)
                  ),
                },
                id: "corridor",
              }),
              classificationType: Cesium.ClassificationType.TERRAIN,
            })
          );

          // Rectangle geometry
          scene.groundPrimitives.add(
            new Cesium.GroundPrimitive({
              geometryInstances: new Cesium.GeometryInstance({
                geometry: new Cesium.RectangleGeometry({
                  rectangle: Cesium.Rectangle.fromDegrees(
                    -100.0,
                    30.0,
                    -90.0,
                    40.0
                  ),
                  rotation: Cesium.Math.toRadians(45),
                }),
                attributes: {
                  color: Cesium.ColorGeometryInstanceAttribute.fromColor(
                    new Cesium.Color(0.0, 1.0, 0.0, 0.5)
                  ),
                },
                id: "rectangle",
              }),
              classificationType: Cesium.ClassificationType.TERRAIN,
            })
          );

          // Rhumb line polygon geometry
          scene.groundPrimitives.add(
            new Cesium.GroundPrimitive({
              geometryInstances: new Cesium.GeometryInstance({
                geometry: new Cesium.PolygonGeometry({
                  polygonHierarchy: new Cesium.PolygonHierarchy(
                    Cesium.Cartesian3.fromDegreesArray([
                      -130,
                      55,
                      -100,
                      55,
                      -100,
                      45,
                      -130,
                      45,
                    ])
                  ),
                  arcType: Cesium.ArcType.RHUMB,
                }),
                attributes: {
                  color: Cesium.ColorGeometryInstanceAttribute.fromColor(
                    new Cesium.Color(1.0, 1.0, 0.0, 0.5)
                  ),
                },
                id: "rhumbPolygon",
              }),
              classificationType: Cesium.ClassificationType.TERRAIN,
            })
          );
        });

        Sandcastle.reset = function () {
          scene.groundPrimitives.removeAll();
          handler = handler && handler.destroy();

          //Set the camera to a US centered tilted view and switch back to moving in world coordinates.
          viewer.camera.lookAt(
            Cesium.Cartesian3.fromDegrees(-98.0, 40.0),
            new Cesium.Cartesian3(0.0, -4790000.0, 3930000.0)
          );
          viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY);
        };

        //Sandcastle_End
        Sandcastle.finishedLoading();
      }
      if (typeof Cesium !== "undefined") {
        window.startupCalled = true;
        startup(Cesium);
      }
    </script>
  </body>
</html>
